package helper

import (
	"fmt"
	"github.com/jinzhu/copier"
	"reflect"
	"time"
)

func RequireTrue(condition bool, message string, a ...any) error {
	if !condition {
		return fmt.Errorf(message, a...)
	}
	return nil
}

func CopyDeep(toValue interface{}, fromValue interface{}) (err error) {
	return copier.CopyWithOption(toValue, fromValue, copier.Option{
		IgnoreEmpty: true,
		DeepCopy:    true,
	})
}

// CopyOut 只复制外层，不复现嵌套继承类型里的
func CopyOut(toValue interface{}, fromValue interface{}) (err error) {
	return copier.CopyWithOption(toValue, fromValue, copier.Option{
		IgnoreEmpty: false,
		DeepCopy:    false,
	})
}

// ConvertList convert a struct list to target list
func ConvertList[T, U any](data []U, converts ...func(*T, U)) []*T {
	list := make([]*T, len(data))
	for i, v := range data {
		var dst T
		_ = CopyDeep(&dst, v)
		for _, convert := range converts {
			convert(&dst, v)
		}
		list[i] = &dst
	}
	return list
}

// ConvertTime2Unix convert origin obj time field to target int64
func ConvertTime2Unix[T, O any]() func(*T, O) {
	return func(t *T, o O) {
		// 原值
		oriValue := reflect.ValueOf(o)
		oriType := reflect.TypeOf(o)
		if oriValue.Kind() == reflect.Ptr {
			oriValue = oriValue.Elem()
			oriType = oriValue.Type()
		}
		// 目标值
		target := reflect.ValueOf(t)
		if target.Kind() == reflect.Ptr {
			target = target.Elem()
		}
		if oriValue.Kind() == reflect.Struct && target.Kind() == reflect.Struct {
			for i := 0; i < oriValue.NumField(); i++ {
				field := oriValue.Field(i)
				if field.Type() == reflect.TypeOf(time.Time{}) {
					// 是时间类型，需要给目录设置转成int64
					name := oriType.Field(i).Name
					dt := field.Interface().(time.Time)
					tField := target.FieldByName(name)
					if tField.IsValid() && tField.CanSet() {
						tField.SetInt(dt.UnixMilli())
					}
				}
			}
		}
	}
}
